跳到主要内容

Rive 事件

⚠️ 弃用通知: 本页文档记录了旧的事件系统。**对于新项目:**请改用数据绑定。**对于现有项目:**计划尽快从事件迁移到数据绑定。此内容仅供旧版支持参考。

视频教程:https://www.youtube.com/watch?v=M5DIDVtYI_Y

通过 Rive 事件,你可以订阅从动画、状态机和 Rive 监听器报告的有意义信号,这些都是在 Rive 编辑器中设计时创建的。这些信号可以在运行时订阅,并具有特定名称、类型和可能伴随事件的各种自定义元数据,以帮助告知围绕其含义的上下文。

关于事件功能的更多信息,请查看文档编辑器部分中的事件页面。事件系统也已扩展为支持音频事件,以在编辑器和运行时触发音频播放。

例如,在模拟加载器的 Rive 图形中,可能有一个名为 LoadComplete 的事件,在从 complete 时间线动画状态过渡到 idle 状态时触发。你可以用一个回调订阅 Rive 事件,运行时可能会调用该回调,并且从那里,你的回调可以在事件触发的合适时刻处理额外的功能。

事件的其他实际用途:

  • 在动画的特定时刻协调音频播放,参见音频事件
  • 在特定交互发生时打开 URL
  • 在有意义的触摸交互上添加触觉反馈
  • 在按钮和其他 UI 元素上实现功能
  • 发送语义信息
  • 在合适时刻传达运行时需要的任何信息

订阅事件

在运行时订阅 Rive 事件时,你订阅的是所有可能从状态机发出的 Rive 事件,并且可以按名称或类型解析每个事件以执行条件逻辑。

让我们使用一个五星评级 Rive 示例来设置随事件提供的任何文本,并在有 URL 时打开它。

示例

高级 API 用法

添加事件监听器

类似于 DOM 元素的 addEventListener() / removeEventListener() API,你将使用 Rive 实例的 on() / off() API 来订阅 Rive 事件。只需提供 RiveEvent 枚举和一个回调,运行时将在检测到任何 Rive 事件的适当时刻调用该回调。

示例用法

import { Rive, EventType, RiveEventType } from '@rive-app/canvas'

const r = new Rive({
src: "/static-assets/star-rating.riv",
artboard: "my-artboard-name",
autoplay: true,
stateMachines: "State Machine 1",
// automaticallyHandleEvents: true, // 自动处理 OpenUrl 事件
onLoad: () => {
r.resizeDrawingSurfaceToCanvas();
},
});

function onRiveEventReceived(riveEvent) {
const eventData = riveEvent.data;
const eventProperties = eventData.properties;
if (eventData.type === RiveEventType.General) {
console.log("Event name", eventData.name);
// 添加了事件的相关元数据
console.log("Rating", eventProperties.rating);
console.log("Message", eventProperties.message);
} else if (eventData.type === RiveEventType.OpenUrl) {
console.log("Event name", eventData.name);
window.open(eventData.url);
}
}

// 添加事件监听器并提供处理 Rive Event 的回调
r.on(EventType.RiveEvent, onRiveEventReceived);
// 可以随时通过 off() API 取消订阅 Rive Events,如下所示
// r.off(EventType.RiveEvent, onRiveEventReceived);

低级 API 用法

使用低级 API(即 @rive-app/canvas-advanced)时,你需要通过创建的状态机实例在渲染循环中自行捕获 Rive 事件(参见低级 API 用法文档)。要实现这一点,在推进状态机之前:

  • 通过状态机的 reportedEventCount() API 确定自上一帧以来报告的 Rive 事件数量
  • 迭代事件并通过状态机的 reportedEventAt(idx) API 获取事件引用
import RiveCanvas, {RiveEventType} from '@rive-app/canvas-advanced';

...
// 渲染循环
function myCustomRenderLoop(timestamp) {
...
const elapsedTimeSec = (timestamp - prevTimestamp) / 1000;
if (stateMachine) {
const numFiredEvents = stateMachine.reportedEventCount();
for (let i = 0; i < numFiredEvents; i++) {
const event = stateMachine.reportedEventAt(i);
// 现在运行任何基于事件的逻辑
if (event.type === RiveEventType.OpenUrl) {
const a = document.createElement("a");
a.setAttribute("href", event.url);
a.setAttribute("target", event.target);
a.click();
}
}
}
// 现在推进
stateMachine.advance(elapsedTimeSec);
...
rive.requestAnimationFrame(myCustomRenderLoop);
}
rive.requestAnimationFrame(myCustomRenderLoop);

额外资源

视频教程:https://www.youtube.com/watch?v=e2bshfKuu8U